using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Data.SqlClient;
using System.Collections;
using System.Data;

namespace Elte.SqlSpIdx
{
    public static class SQLmethods
    {
        [Microsoft.SqlServer.Server.SqlFunction(
                DataAccess = DataAccessKind.Read, FillRowMethodName = "Distances",
                IsDeterministic = true, IsPrecise = true,
                TableDefinition = "Id bigint,Distance float")]
        public static IEnumerable NearestNeighbors(SqlString indexortable, SqlBinary coord, SqlInt32 N)
        {
            try
            {
                //Ienumerable do not dispose connection
                SqlConnection cn = new SqlConnection(Constants.MyConnectionString);
                cn.Open();

                Index I = Core.GetSuitableIndex(cn, IndexFunctionType.NN, (string)indexortable);
                double[] C = Converters.VectorConverter.ToArray(coord);

                int numberofpoints = (int)N;
                return I.NearestNeighborsIndex(C, (int)N);
            }
            catch (Exception)
            {

                throw;
            }
        }



        //[Microsoft.SqlServer.Server.SqlFunction(
        //     DataAccess = DataAccessKind.Read, FillRowMethodName = "Distances",
        //     IsDeterministic = true, IsPrecise = true,
        //     TableDefinition = "Id bigint,Distance float")]
        //public static IEnumerable SpherePoints(SqlString indexortable, SqlBinary coord, SqlDouble R)
        //{
        //    try
        //    {
        //        //Ienumerable do not dispose connection
        //        SqlConnection cn = new SqlConnection(Constants.MyConnectionString);
        //        cn.Open();


        //        Index I = Core.GetSuitableIndex(cn, IndexFunctionType.NN, (string)indexortable);
        //        double[] C = Converters.VectorConverter.ToArray(coord);



        //        return I.SpherePoints(C, (double)R);
        //    }
        //    catch (Exception)
        //    {

        //        throw;
        //    }
        //}






        public static void IdsOnly(object row, out long Id)
        {
            Id = (long)((object[])row)[0];
        }




        public static void EstimateValues(object row, out double N1, out double N2, out double N3, out double N4)
        {

            N1 = ((double[])row)[0];
            N2 = ((double[])row)[1];
            N3 = ((double[])row)[2];
            N4 = ((double[])row)[3];
        }
        public static void Distances(object row, out long Id, out double Distance)
        {
            Id = ((KeyValuePair<long, double>)row).Key;
            Distance = ((KeyValuePair<long, double>)row).Value;

        }
        [Microsoft.SqlServer.Server.SqlProcedure]
        public static void CreateIndexDetailed(SqlString type, SqlString name, SqlString description, SqlString table,
            SqlString primaryKeyColumn, SqlString indexColumn, SqlString dataColumn, SqlString dataColumnNames, SqlString options)
        {
            Core.CreateindexDetailed((string)type, (string)name, (string)description, (string)table, (string)primaryKeyColumn, (string)indexColumn, (string)dataColumn, (string)dataColumnNames, (string)options);
        }




        [Microsoft.SqlServer.Server.SqlProcedure]
        public static void CreateIndex(SqlString name, SqlString table, SqlString columns)
        {
            Core.Createindex((string)name, (string)table, (string)columns);

        }



        #region SpatialQuery

        [Microsoft.SqlServer.Server.SqlFunction(
               DataAccess = DataAccessKind.Read, FillRowMethodName = "IdsOnly",
               IsDeterministic = true, IsPrecise = true,
               TableDefinition = "Id bigint")]
        public static IEnumerable f_SpatialQuery(SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        {
            return Core.SpatialQueryGeneral(null, (string)tableorindex, (string)spatialwhere, (string)sqlwhere,true);
        }

        [Microsoft.SqlServer.Server.SqlFunction(
             DataAccess = DataAccessKind.Read, FillRowMethodName = "FillRow1Float",
             IsDeterministic = true, IsPrecise = true,
             TableDefinition = "R1 float")]
        public static IEnumerable f_SpatialQuery_1(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        {
            return Core.SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere, true);
        }

        [Microsoft.SqlServer.Server.SqlFunction(
             DataAccess = DataAccessKind.Read, FillRowMethodName = "FillRow2Float",
             IsDeterministic = true, IsPrecise = true,
             TableDefinition = "R1 float,R2 float")]
        public static IEnumerable f_SpatialQuery_2(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        {
            return Core.SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere, true);
        }

        [Microsoft.SqlServer.Server.SqlFunction(
            DataAccess = DataAccessKind.Read, FillRowMethodName = "FillRow3Float",
            IsDeterministic = true, IsPrecise = true,
            TableDefinition = "R1 float,R2 float,R3 float")]
        public static IEnumerable f_SpatialQuery_3(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        {
            return Core.SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere, true);
        }

        [Microsoft.SqlServer.Server.SqlFunction(
            DataAccess = DataAccessKind.Read, FillRowMethodName = "FillRow4Float",
            IsDeterministic = true, IsPrecise = true,
            TableDefinition = "R1 float,R2 float,R3 float,R4 float")]
        public static IEnumerable f_SpatialQuery_4(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        {
            return Core.SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere, true);
        }
        public static void FillRow1Float(object row, out double R1)
        {
            R1 = Common.UnboxDouble (((object[])row)[0]);
        }

        public static void FillRow2Float(object row, out double R1, out double R2)
        {
            R1 = Common.UnboxDouble(((object[])row)[0]);
            R2 = Common.UnboxDouble(((object[])row)[1]);
        }

        public static void FillRow3Float(object row, out double R1, out double R2, out double R3)
        {
            R1 = Common.UnboxDouble(((object[])row)[0]);
            R2 = Common.UnboxDouble(((object[])row)[1]);
            R3 = Common.UnboxDouble(((object[])row)[2]);
        }

        public static void FillRow4Float(object row, out double R1, out double R2, out double R3,out double R4)
        {
            R1 = Common.UnboxDouble(((object[])row)[0]);
            R2 = Common.UnboxDouble(((object[])row)[1]);
            R3 = Common.UnboxDouble(((object[])row)[2]);
            R4 = Common.UnboxDouble(((object[])row)[3]);
        }
        [Microsoft.SqlServer.Server.SqlProcedure]
        public static void SpatialQuery(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        {

            Core.SpatialQuery((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere);
        }



        //[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read, IsPrecise = true,
        //    FillRowMethodName = "SpatialQuery_1_Fill", TableDefinition = "c1 float")]
        //public static IEnumerable SpatialQuery_1(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        //{
        //    return SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere);
        //}


        public static void SpatialQuery_1_Fill(object row, out double c1)
        {
            c1 = (double)(((object[])row)[0]);
        }
        //[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read, IsPrecise = true,
        //   FillRowMethodName = "SpatialQuery_2_Fill", TableDefinition = "c1 float,c2 float")]
        //public static IEnumerable SpatialQuery_2(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        //{
        //    return SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere);
        //}


        public static void SpatialQuery_2_Fill(object row, out double c1, out double c2)
        {
            c1 = (double)(((object[])row)[0]);
            c2 = (double)(((object[])row)[1]);
        }


        //[Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read, IsPrecise = true,
        //FillRowMethodName = "SpatialQuery_3_Fill", TableDefinition = "c1 float,c2 float,c3 float")]
        //public static IEnumerable SpatialQuery_3(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        //{
        //    return SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere);
        //}


        public static void SpatialQuery_3_Fill(object row, out double c1, out double c2, out double c3)
        {
            c1 = (double)(((object[])row)[0]);
            c2 = (double)(((object[])row)[1]);
            c3 = (double)(((object[])row)[2]);
        }


        // [Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read, IsPrecise = true,
        //FillRowMethodName = "SpatialQuery_4_Fill", TableDefinition = "c1 float,c2 float,c3 float,c4 float")]
        // public static IEnumerable SpatialQuery_4(SqlString selectlist, SqlString tableorindex, SqlString spatialwhere, SqlString sqlwhere)
        // {
        //     return SpatialQueryGeneral((string)selectlist, (string)tableorindex, (string)spatialwhere, (string)sqlwhere);
        // }
        // public static void SpatialQuery_4_Fill(object row, out double c1, out double c2, out double c3, out double c4)
        // {
        //     c1 = (double)(((object[])row)[0]);
        //     c2 = (double)(((object[])row)[1]);
        //     c3 = (double)(((object[])row)[2]);
        //     c4 = (double)(((object[])row)[3]);
        // }


        #endregion


    }
}
